home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-01-03 | 49.3 KB | 1,958 lines |
- Newsgroups: comp.sources.unix
- From: lm03_cif@uhura.cc.rochester.edu (Larry Moss)
- Subject: v25i090: letters - game to improve typing skills
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: lm03_cif@uhura.cc.rochester.edu (Larry Moss)
- Posting-Number: Volume 25, Issue 90
- Archive-Name: letters
-
- Here is "letters", the "Letter Invader" game. It is pretty cute. It is less
- stressful than Tetris, but it might be a good diversion while waiting
- for something to compile.
-
- Abstract (lifted from the man page):
-
- Letters is based on Letter Invaders which was around in the
- PC environment several years ago. It in turn was based on
- the popular arcade style game, Space Invaders. For those
- not familiar with Space Invaders (please let me know if
- you're one of these people and let me know what planet
- you've been living on :-) the idea is to blast aliens out of
- the sky as they attempt to land on and "kill" you. Since
- this is a game to improve typing skills, the aliens are
- words selected randomly from the dictionary. You blast the
- aliens out of the sky by typing them correctly.
-
- Nick
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: config.h highscore.c kinput.c kinput.h letters.c term.c
- # term.h terms.h usleep.c usleep5.c word.c Makefile letters.man
- # letters.high README
- # Wrapped by lm03_cif@troi.cc.rochester.edu on Wed Jan 1 10:40:44 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'config.h'\"
- else
- echo shar: Extracting \"'config.h'\" \(1720 characters\)
- sed "s/^X//" >'config.h' <<'END_OF_FILE'
- X/*
- X * configurable stuff in letters. Most things here probably shouldn't need
- X * to be changed but are here because someone may want to tinker with this
- X * stuff to affect the way it performs on different systems. The stuff
- X * most likely to require changes is at the top of the file.
- X */
- X#ifndef DICTIONARY
- X#define DICTIONARY "/usr/dict/words"
- X#endif
- X
- X#ifndef HIGHSCORES
- X#define HIGHSCORES "letters.high"
- X#endif
- X
- X/*
- X * probably best to leave these so it's the same everywhere. Otherwise,
- X * anyone with an xterminal is likely to get higher scores.
- X */
- X#ifdef AMIGA
- X#define SCREENLENGTH 22
- X#else
- X#define SCREENLENGTH 23
- X#endif
- X#define SCREENWIDTH 80
- X
- X/*
- X * initial delay in usecs before words move to the next line
- X */
- X#define START_DELAY 750000
- X
- X/*
- X * this implements "graduated" (non-linear) decreasing delay times:
- X * each level, delay gets reduced by smaller and smaller amounts
- X * (eventually, when delay would get below PAUSE, it is simply set to PAUSE)
- X *
- X * if you change START_DELAY or DELAY_CHANGE, DECEL must be tuned carefully,
- X * otherwise DELAY(lev) will drop suddenly to PAUSE at some point
- X */
- X#define DELAY_CHANGE 60000
- X#define DECEL 1200
- X#define DELAY(lev) ( ((lev)*DECEL > DELAY_CHANGE/2) ? PAUSE :\
- X (START_DELAY-(DELAY_CHANGE-(lev)*DECEL)*(lev)) )
- X
- X/*
- X * number of words to be completed before level change
- X */
- X#define LEVEL_CHANGE 15
- X
- X/*
- X * length of pause before reading keyboard again (in usecs). There has to
- X * be some pause.
- X */
- X#define PAUSE 10000
- X
- X/*
- X * This is how likely it is that another word will appear on the screen
- X * while words are falling. there isa 1/ADDWORD chance of a new word
- X */
- X#define ADDWORD 6
- X
- X/*
- X * length of words in bonus round
- X */
- X#define BONUSLENGTH 10
- END_OF_FILE
- if test 1720 -ne `wc -c <'config.h'`; then
- echo shar: \"'config.h'\" unpacked with wrong size!
- fi
- # end of 'config.h'
- fi
- if test -f 'highscore.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'highscore.c'\"
- else
- echo shar: Extracting \"'highscore.c'\" \(3677 characters\)
- sed "s/^X//" >'highscore.c' <<'END_OF_FILE'
- X/*
- X * read and update high score file for Letter Invaders
- X *
- X * copyright 1991 by Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X */
- X
- X#include <stdio.h>
- X#ifdef AMIGA
- X# include <stdlib.h>
- X# include <string.h>
- X#else
- X# include <pwd.h>
- X#endif
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "config.h"
- X#include "term.h"
- X#include "terms.h"
- X#include "kinput.h"
- X
- Xstruct score_rec {
- X char name[9];
- X int level, words, score;
- X};
- X
- Xstatic char highscores[] = HIGHSCORES;
- X
- Xextern unsigned score, word_count, level;
- X
- Xstatic struct score_rec high_scores[10];
- Xstatic struct stat s_buf;
- Xtime_t readtime;
- X
- Xvoid read_scores() {
- X int i;
- X FILE *fp;
- X
- X /*
- X * get the last modified time so we know later if we have to reread
- X * the scores before saving a new file.
- X */
- X if(stat(highscores, &s_buf) == -1) {
- X fprintf(stderr, "Cannot stat %s: ", highscores);
- X perror("");
- X exit(1);
- X }
- X
- X readtime = s_buf.st_mtime;
- X
- X if((fp = fopen(highscores, "r")) == NULL) {
- X fprintf(stderr, "Cannot open %s: ", highscores);
- X perror("");
- X exit(1);
- X }
- X
- X for(i = 0; i < 10; i++) {
- X fscanf(fp, "%s%d%d%d", high_scores[i].name,
- X &high_scores[i].level, &high_scores[i].words,
- X &high_scores[i].score);
- X }
- X
- X fclose(fp);
- X}
- X
- Xint write_scores() {
- X int i;
- X FILE *fp;
- X
- X /*
- X * check to make sure the high score list has not been modified
- X * since we read it.
- X */
- X if(stat(highscores, &s_buf) == -1) {
- X fprintf(stderr, "Cannot stat %s: ", highscores);
- X perror("");
- X setterm(ORIG);
- X exit(1);
- X }
- X
- X if(s_buf.st_mtime > readtime)
- X return -1;
- X
- X if((fp = fopen(highscores, "w")) == NULL) {
- X fprintf(stderr, "Cannot write to %s: ", highscores);
- X perror("");
- X setterm(ORIG);
- X exit(1);
- X }
- X
- X for(i = 0; i < 10; i++) {
- X fprintf(fp, "%s %d %d %d", high_scores[i].name,
- X high_scores[i].level, high_scores[i].words,
- X high_scores[i].score);
- X }
- X
- X fclose(fp);
- X}
- X
- X
- X
- Xvoid update_scores() {
- X int i, j;
- X#ifdef AMIGA
- X char *u;
- X#else
- X struct passwd *p;
- X#endif
- X
- X for(i = 0; i < 10; i++)
- X if(score > high_scores[i].score) {
- X for(j = 10; j > i; j--) {
- X strcpy(high_scores[j].name, high_scores[j-1].name);
- X high_scores[j].words = high_scores[j-1].words;
- X high_scores[j].score = high_scores[j-1].score;
- X high_scores[j].level = high_scores[j-1].level;
- X }
- X#ifdef AMIGA
- X if((u = getenv("USER")) == NULL) {
- X char buffer[128],*p;
- X clrdisp();
- X gotoxy(18, 5);
- X cooked(stdin);
- X fputs("Enter your name (8 char. max, no spaces): ",stdout);
- X fflush(stdout);
- X gets(buffer);
- X if((p=strchr(buffer,' ')))
- X *p='\0';
- X if(!buffer[0])
- X strcpy(buffer,"nobody");
- X strncpy(high_scores[i].name, buffer, 8);
- X raw(stdin);
- X } else
- X strcpy(high_scores[i].name, u);
- X#else
- X if((p = getpwuid(getuid())) == NULL)
- X strcpy(high_scores[i].name, "nobody");
- X else
- X strcpy(high_scores[i].name, p->pw_name);
- X#endif
- X high_scores[i].score = score;
- X high_scores[i].words = word_count;
- X high_scores[i].level = level;
- X if(write_scores() == -1) {
- X read_scores();
- X update_scores();
- X }
- X break;
- X }
- X}
- X
- Xvoid show_scores() {
- X int i;
- X
- X clrdisp();
- X gotoxy(18, 5);
- X highlight(1);
- X printf("Top Ten Scores for Letter Invaders");
- X highlight(0);
- X gotoxy(20, 7);
- X underline(1);
- X printf(" name level words score");
- X underline(0);
- X
- X for(i = 0; i < 10; i++) {
- X gotoxy(18, 8 + i);
- X printf("%3d %-10s%5d%6d%6d", i+1, high_scores[i].name,
- X high_scores[i].level, high_scores[i].words,
- X high_scores[i].score);
- X }
- X
- X printf("\n");
- X#ifdef AMIGA
- X {
- X char bogus;
- X fputs("\nPress RETURN... ",stdout);
- X fflush(stdout);
- X bogus=getchar();
- X }
- X#endif
- X}
- END_OF_FILE
- if test 3677 -ne `wc -c <'highscore.c'`; then
- echo shar: \"'highscore.c'\" unpacked with wrong size!
- fi
- # end of 'highscore.c'
- fi
- if test -f 'kinput.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'kinput.c'\"
- else
- echo shar: Extracting \"'kinput.c'\" \(3666 characters\)
- sed "s/^X//" >'kinput.c' <<'END_OF_FILE'
- X/*
- X * do non-blocking keyboard reads
- X *
- X * copyright 1991 by Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X/* I know some systems prefer time.h, but I'm not sure which */
- X#include <sys/time.h>
- X#ifdef SYSV
- X#include <termio.h>
- X#else /* SYSV */
- X#include <sgtty.h>
- X#endif /* SYSV */
- X
- X#include "kinput.h"
- X#include "terms.h"
- X#include "term.h"
- X
- X#define SCREENLENGTH 24
- X
- Xextern unsigned int score, word_count, level;
- X
- Xint key_pressed();
- X
- Xstatic interrupt();
- X
- X#ifndef NOJOB
- Xstatic pause();
- Xstatic cont();
- X#endif
- X
- Xstatic die();
- X
- X/*
- X * This function will return -1 if no key is available, or the key
- X * that was pressed by the user. It is checking stdin, without blocking.
- X */
- Xint key_pressed()
- X{
- X#ifdef SYSV
- X int chars_read;
- X static char keypressed;
- X
- X chars_read = read(0, &keypressed, 1);
- X if (chars_read == 1)
- X return((int)keypressed);
- X return(-1);
- X#else /* SYSV */
- X int mask = 1, chars_read;
- X static char keypressed;
- X struct timeval waittime;
- X
- X waittime.tv_sec=0;
- X waittime.tv_usec=4;
- X if (select(1, &mask, 0, 0, &waittime)) {
- X chars_read = read(0, &keypressed, 1);
- X if (chars_read == 1)
- X return((int)keypressed);
- X }
- X return(-1);
- X#endif /* SYSV */
- X}
- X
- X/*
- X * Set the terminal to cbreak mode, turn off echo and prevent special
- X * characters from affecting the input. We will handle EOF and other fun
- X * stuff our own way. Backup copies of the current setup will be kept
- X * to insure the terminal gets returned to its initial state.
- X */
- Xvoid setterm(setting)
- Xint setting;
- X{
- X#ifdef SYSV
- X struct termio termrec;
- X static struct termio old_termrec;
- X#else /* SYSV */
- X struct sgttyb termrec;
- X struct tchars trec;
- X static struct tchars old_trec;
- X static struct sgttyb old_termrec;
- X#endif /* SYSV */
- X
- X if(setting == NEW) {
- X signal(SIGINT, interrupt);
- X signal(SIGQUIT, die);
- X signal(SIGTERM, die);
- X#ifndef NOJOB
- X signal(SIGTSTP, pause);
- X signal(SIGCONT, cont);
- X#endif /* NOJOB */
- X
- X#ifdef SYSV
- X ioctl(0, TCGETA, &termrec);
- X old_termrec = termrec;
- X termrec.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
- X termrec.c_iflag |= BRKINT;
- X termrec.c_lflag &= ~(ICANON|ECHO);
- X termrec.c_cc[VTIME] = 0;
- X termrec.c_cc[VMIN] = 0;
- X ioctl(0, TCSETAF, &termrec);
- X#else /* SYSV */
- X ioctl(0, TIOCGETP, &termrec);
- X old_termrec = termrec;
- X termrec.sg_flags |= CBREAK;
- X termrec.sg_flags &= ~ECHO;
- X ioctl(0, TIOCSETP, &termrec);
- X
- X ioctl(0, TIOCGETC, &trec);
- X old_trec = trec;
- X trec.t_eofc = (char) -1;
- X trec.t_quitc = (char) -1;
- X ioctl(0, TIOCSETC, &trec);
- X#endif /* SYSV */
- X }
- X else {
- X signal(SIGINT, SIG_DFL);
- X signal(SIGQUIT, SIG_DFL);
- X signal(SIGTERM, SIG_DFL);
- X#ifndef NOJOB
- X signal(SIGTSTP, SIG_DFL);
- X#endif /* NOJOB */
- X
- X#ifdef SYSV
- X ioctl(0, TCSETAF, &old_termrec);
- X#else /* SYSV */
- X ioctl(0, TIOCSETP, &old_termrec);
- X ioctl(0, TIOCSETC, &old_trec);
- X#endif /* SYSV */
- X }
- X}
- X
- X
- X/*
- X * Interrupt handlers
- X */
- X
- X#ifndef NOJOB
- Xstatic pause(sig)
- Xint sig;
- X{
- X#ifdef SYSV
- X signal(sig, interrupt);
- X#endif /* SYSV */
- X gotoxy(0, SCREENLENGTH);
- X setterm(ORIG);
- X putchar('\n');
- X kill(getpid(), SIGSTOP);
- X}
- X
- Xstatic cont(sig)
- Xint sig;
- X{
- X#ifdef SYSV
- X signal(sig, interrupt);
- X#endif /* SYSV */
- X setterm(NEW);
- X redraw();
- X}
- X
- X#endif /* NOJOB */
- X
- Xstatic interrupt(sig)
- Xint sig;
- X{
- X char c;
- X
- X setterm(ORIG);
- X printf("\n\rare you sure you want to quit? ");
- X if((c = getchar()) == 'y' || c == 'Y') {
- X clrdisp();
- X printf("\n\nfinal: score = %u\twords = %u\t level = %d\n",
- X score, word_count, level);
- X highlight(0);
- X exit(1);
- X } else {
- X#ifdef SYSV
- X signal(sig, interrupt);
- X#endif /* SYSV */
- X setterm(NEW);
- X redraw();
- X }
- X}
- X
- Xstatic die(sig)
- Xint sig;
- X{
- X setterm(ORIG);
- X clrdisp();
- X highlight(0);
- X exit(1);
- X}
- END_OF_FILE
- if test 3666 -ne `wc -c <'kinput.c'`; then
- echo shar: \"'kinput.c'\" unpacked with wrong size!
- fi
- # end of 'kinput.c'
- fi
- if test -f 'kinput.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'kinput.h'\"
- else
- echo shar: Extracting \"'kinput.h'\" \(323 characters\)
- sed "s/^X//" >'kinput.h' <<'END_OF_FILE'
- X/*
- X * header file for:
- X * kinput.c: Larry Moss (lm03_cif@cc.rochester.edu)
- X * Fall, 1990
- X *
- X */
- X
- X#define BACKSPACE fputs("\b \b", stdout)
- X#define DEL 127
- X#define WERASE 23
- X#define KILL 21
- X#define TAB 9
- X#define ESC 27
- X#define CTL(c) (c & 037)
- X#define MAXLENGTH 1024
- X#define NEW 1
- X#define ORIG 0
- X
- Xvoid setterm();
- END_OF_FILE
- if test 323 -ne `wc -c <'kinput.h'`; then
- echo shar: \"'kinput.h'\" unpacked with wrong size!
- fi
- # end of 'kinput.h'
- fi
- if test -f 'letters.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'letters.c'\"
- else
- echo shar: Extracting \"'letters.c'\" \(12891 characters\)
- sed "s/^X//" >'letters.c' <<'END_OF_FILE'
- X/*
- X * letters.c: A simple game to help improve typing skills.
- X *
- X * copyright 1991 Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X */
- X
- X#define CTRL(c) (c & 037)
- X#define TRUE 1
- X#define FALSE 0
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <time.h>
- X#ifdef AMIGA
- X# include <math.h>
- X#endif
- X#include "config.h"
- X#include "kinput.h"
- X#include "terms.h"
- X#include "term.h"
- X
- X#if defined(SYSV)
- X# define srandom srand48
- X# define random lrand48
- X#endif
- X
- Xstruct s_word {
- X struct s_word *nextword;
- X int posx;
- X int posy;
- X int length;
- X int drop;
- X int matches;
- X char word[1]; /* extensible */
- X};
- X
- Xint move();
- Xvoid putword();
- Xint game();
- Xvoid redraw();
- Xvoid erase();
- Xvoid status();
- Xvoid new_level();
- Xvoid banner();
- Xstruct s_word *newword();
- Xstruct s_word *searchstr(), *searchchar();
- Xvoid kill_word();
- Xint (*ding)();
- X
- Xchar *malloc();
- Xvoid free();
- X
- X/*
- X * There are too many globals for my taste, but I took the easy way out in
- X * a few places
- X */
- Xunsigned int score = 0;
- Xunsigned int level = 0;
- Xint levels_played = -1;
- Xunsigned int word_count = 0;
- Xstatic int lives = 2;
- Xstatic long delay;
- Xstruct s_word *words, *lastword, *prev_word;
- Xint bonus = FALSE; /* to determine if we're in a bonus round */
- Xint wpm = 0;
- Xint letters = 0;
- X
- Xvoid usage(progname)
- Xchar *progname;
- X{
- X fprintf(stderr, "Usage: %s [-q | -b] [-l#]\n", progname);
- X fprintf(stderr, " %s [-h]\n", progname);
- X exit(0);
- X}
- X
- Xvoid main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X char *progname;
- X int foo;
- X
- X /*
- X * make sure the person is on a tty
- X */
- X if(!isatty(0)) {
- X fputs("where are you?\n", stderr);
- X exit(1);
- X }
- X
- X /*
- X * this should also really check to make sure it's being played on
- X * the terminal of the person running it. People around here have
- X * the habit of redirecting random programs to other screens.
- X */
- X if(!isatty(1)) {
- X fputs("This game can only be played on a terminal!\n", stderr);
- X exit(0);
- X }
- X
- X /*
- X * default bell sound
- X */
- X ding = quiet;
- X
- X /*
- X * initialize display stuff
- X */
- X init_term(); /* termcap stuff */
- X
- X /*
- X * get name of program
- X */
- X#ifdef AMIGA
- X if(argc==0) { /* called from Workbench */
- X progname="letters";
- X argv[1]=NULL;
- X } else
- X#endif
- X progname = argv[0];
- X
- X /*
- X * check for options
- X */
- X while(*++argv) {
- X if((*argv)[0] == '-') {
- X switch((*argv)[1]) {
- X case 'b':
- X ding = bell;
- X break;
- X case 'q':
- X ding = quiet;
- X break;
- X case 'h':
- X read_scores();
- X show_scores();
- X exit(0);
- X break;
- X case 'l':
- X sscanf(&argv[0][2], "%d", &level);
- X if(DELAY(level) < PAUSE) {
- X fprintf(stderr, "You may not start at level %d\n", level);
- X exit(0);
- X }
- X break;
- X default:
- X usage(progname);
- X }
- X } else {
- X usage(progname);
- X }
- X }
- X
- X /*
- X * get stuff initialized
- X */
- X#ifdef AMIGA
- X fixedwin(argc,progname);
- X#endif
- X setterm(NEW); /* signal stuff, keyboard stuff */
- X srandom(getpid());
- X clrdisp();
- X new_level();
- X status();
- X words = NULL;
- X
- X for(;;) {
- X /*
- X * allocate memory for the first word and then find a word
- X * if there are no others on the screen. There must always
- X * be at least one word active.
- X */
- X if(words == NULL) {
- X lastword = words = newword((struct s_word *)NULL);
- X prev_word = NULL;
- X putword(lastword);
- X }
- X
- X if(game() == 0) {
- X /*
- X * all finished. print score and clean up.
- X */
- X gotoxy(0, SCREENLENGTH);
- X fflush(stdout);
- X putchar('\n');
- X break;
- X }
- X }
- X
- X read_scores();
- X update_scores();
- X sleep(2);
- X show_scores();
- X printf("\n\nfinal: score = %u\twords = %u\t level = %d\n",
- X score, word_count, level);
- X
- X /*
- X * flush keyboard and quit.
- X */
- X while(key_pressed() != -1);
- X setterm(ORIG);
- X exit(0);
- X}
- X
- X/*
- X * move all words down 1 or more lines.
- X * return the number of words that have fallen off the bottom of the screen
- X */
- Xint move()
- X{
- X struct s_word *wordp, *next;
- X int died;
- X
- X died = 0;
- X for(wordp = words; wordp != NULL; wordp = next) {
- X next = wordp->nextword;
- X erase(wordp);
- X wordp->posy += wordp->drop;
- X
- X if(wordp->posy >= SCREENLENGTH) {
- X kill_word(wordp);
- X died++;
- X }
- X else {
- X putword(wordp);
- X }
- X }
- X return died;
- X}
- X
- X/*
- X * erase a word on the screen by printing the correct number of blanks
- X */
- Xvoid erase(wordp)
- Xstruct s_word *wordp;
- X{
- X int i;
- X
- X gotoxy(wordp->posx, wordp->posy);
- X for(i = 0; i < wordp->length; i++)
- X putchar(' ');
- X}
- X
- X/*
- X * write the word to the screen with already typed letters highlighted
- X */
- Xvoid putword(wordp)
- Xstruct s_word *wordp;
- X{
- X int i;
- X
- X gotoxy(wordp->posx, wordp->posy);
- X
- X /*
- X * print the letters in the word that have so far been matched
- X * correctly.
- X */
- X highlight(1);
- X for(i = 0; i < wordp->matches; i++)
- X putchar(wordp->word[i]);
- X highlight(0);
- X
- X /*
- X * print the rest of the word.
- X */
- X for(i = wordp->matches; i < wordp->length; i++)
- X putchar(wordp->word[i]);
- X}
- X
- X/*
- X * Here's the main routine of the actual game.
- X */
- Xint game()
- X{
- X int key;
- X unsigned i;
- X int died;
- X struct s_word *curr_word, *temp_word;
- X
- X /*
- X * look to see if we already have a partial match, if not
- X * set the current word pointer to the first word
- X */
- X for(curr_word = words; curr_word; curr_word = curr_word->nextword)
- X if (curr_word->matches > 0)
- X break;
- X if (!curr_word)
- X curr_word = words;
- X
- X while(curr_word->matches < curr_word->length) {
- X for(i = 0; i < delay; i+= PAUSE) {
- X while((curr_word->matches != curr_word->length) &&
- X ((key = key_pressed()) != -1)) {
- X if(key == CTRL('L')) {
- X redraw();
- X continue;
- X }
- X if(key == CTRL('N')) {
- X level++;
- X delay = DELAY(level);
- X if(delay < PAUSE)
- X delay = PAUSE;
- X status();
- X continue;
- X }
- X /*
- X * This stuff deals with collecting letters
- X * for a word that has already been
- X * started. It's kind of clumsy the way
- X * it's being done now and should be
- X * cleaned up, but the obvious combination
- X * of erase() and putword() generate too
- X * much output to be used at 2400 baud. (I
- X * can't play too often at work)
- X */
- X if(curr_word->matches > 0 &&
- X key == curr_word->word[curr_word->matches]) {
- X gotoxy(curr_word->posx + curr_word->matches, curr_word->posy);
- X highlight(1);
- X putchar(curr_word->word[curr_word->matches]);
- X highlight(0);
- X gotoxy(SCREENWIDTH,SCREENLENGTH);
- X fflush(stdout);
- X curr_word->matches++;
- X /*
- X * fill the word with characters to
- X * "explode" it.
- X */
- X if(curr_word->matches >= curr_word->length)
- X for (i = 0; i<curr_word->length; i++)
- X curr_word->word[i] = '-';
- X continue;
- X
- X } else if(temp_word = searchstr(key,
- X curr_word->word,
- X curr_word->matches)) {
- X erase(temp_word);
- X temp_word->matches = curr_word->matches;
- X curr_word->matches = 0;
- X putword(curr_word);
- X curr_word = temp_word;
- X curr_word->matches++;
- X } else if(temp_word = searchchar(key)) {
- X erase(temp_word);
- X curr_word->matches = 0;
- X putword(curr_word);
- X curr_word = temp_word;
- X curr_word->matches++;
- X } else {
- X ding();
- X curr_word->matches = 0;
- X }
- X erase(curr_word);
- X putword(curr_word);
- X gotoxy(SCREENWIDTH,SCREENLENGTH);
- X
- X fflush(stdout);
- X }
- X usleep(PAUSE);
- X }
- X
- X died = move(); /* NB: move may invalidate curr_word */
- X if (died > 0)
- X {
- X /*
- X * we only subtract lives if a word reaches the
- X * bottom in a normal round. If a word reaches
- X * bottom during bonus play, just end the bonus
- X * round.
- X */
- X if(bonus == FALSE)
- X lives -= died;
- X else if(died > 0)
- X new_level();
- X
- X if (lives < 0)
- X lives = 0;
- X status();
- X gotoxy(SCREENWIDTH,SCREENLENGTH);
- X fflush(stdout);
- X return (lives != 0);
- X } else {
- X gotoxy(SCREENWIDTH,SCREENLENGTH);
- X fflush(stdout);
- X }
- X if((random() % ADDWORD) == 0) {
- X lastword = newword(lastword);
- X putword(lastword);
- X }
- X }
- X
- X /*
- X * all letters in the word have been correctly typed.
- X */
- X
- X /*
- X * erase the word
- X */
- X if(curr_word->length == curr_word->matches) {
- X ding(); ding();
- X erase(curr_word);
- X }
- X
- X /*
- X * add on an appropriate score.
- X */
- X score += curr_word->length + (2 * level);
- X letters+= curr_word->length;
- X word_count++;
- X status();
- X
- X /*
- X * delete the completed word and revise pointers.
- X */
- X kill_word(curr_word);
- X
- X /*
- X * increment the level if it's time.
- X */
- X if(word_count % LEVEL_CHANGE == 0)
- X new_level();
- X
- X return 1;
- X}
- X
- X
- X/*
- X * clear the screen and redraw it
- X */
- Xvoid redraw() {
- X clrdisp();
- X status();
- X fflush(stdout);
- X}
- X
- X/*
- X * display the status line in inverse video
- X */
- Xvoid status() {
- X static char line[SCREENWIDTH];
- X int i;
- X
- X sprintf(line, "Score: %-7uLevel: %-3uWords: %-6uLives: %-3dWPM: %-4d",
- X score, level, word_count, lives, wpm);
- X
- X /*
- X * fill the line with spaces
- X */
- X for(i = strlen(line); i < SCREENWIDTH - 2; i++)
- X line[i] = ' ';
- X
- X highlight(1);
- X gotoxy(0, SCREENLENGTH);
- X fputs(line, stdout);
- X highlight(0);
- X}
- X
- X/*
- X * do stuff to change levels. This is where special rounds can be stuck in.
- X */
- Xvoid new_level()
- X{
- X struct s_word *next, *wordp;
- X static time_t last_time = 0L;
- X time_t curr_time;
- X
- X /*
- X * update the words per minute
- X */
- X time(&curr_time);
- X wpm = (letters / 5) / ((curr_time - last_time) / 60.0);
- X last_time = curr_time;
- X letters = 0;
- X
- X /*
- X * if we're inside a bonus round we don't need to change anything
- X * else so just take us out of the bonus round and exit this routine
- X */
- X if(bonus == TRUE) {
- X bonus = FALSE;
- X banner("Bonus round finished");
- X
- X /*
- X * erase all existing words so we can go back to a normal
- X * round
- X */
- X for(wordp = words; wordp != NULL; wordp = next) {
- X next = wordp->nextword;
- X kill_word(wordp);
- X }
- X
- X status();
- X return;
- X }
- X
- X levels_played++;
- X
- X /*
- X * If you start at a level other than 1, the level does not
- X * actually change until you've completed a number of levels equal
- X * to the starting level.
- X */
- X if(level <= levels_played)
- X level++;
- X
- X delay = DELAY(level);
- X
- X /*
- X * no one should ever reach a level where there is no delay, but
- X * just to be safe ...
- X */
- X if(delay < PAUSE)
- X delay = PAUSE;
- X
- X if((levels_played % 3 == 0) && (levels_played != 0)) {
- X bonus = TRUE;
- X
- X /*
- X * erase all existing words so we can have a bonus round
- X */
- X for(wordp = words; wordp != NULL; wordp = next) {
- X next = wordp->nextword;
- X kill_word(wordp);
- X }
- X
- X banner("Prepare for bonus words");
- X lives++;
- X }
- X
- X status();
- X}
- X
- X/*
- X * allocate memory for a new word and get it all set up to use.
- X */
- Xstruct s_word *newword(wordp)
- Xstruct s_word *wordp;
- X{
- X struct s_word *nword;
- X char *word, *getword(), *bonusword();
- X int length;
- X
- X if(bonus == TRUE)
- X word = bonusword();
- X else
- X word = getword();
- X
- X length = strlen(word);
- X
- X nword = (struct s_word *)malloc(sizeof(struct s_word) + length);
- X if(nword == (struct s_word *)0) {
- X perror("\nmalloc");
- X setterm(ORIG);
- X exit(1);
- X }
- X
- X strncpy(nword->word, word, length);
- X nword->length = length;
- X nword->drop = length > 6 ? 1 : length > 3 ? 2 : 3;
- X nword->matches = 0;
- X nword->posx = random() % ((SCREENWIDTH - 1) - nword->length);
- X nword->posy = 0;
- X nword->nextword = NULL;
- X
- X if(wordp != NULL)
- X wordp->nextword = nword;
- X
- X return nword;
- X}
- X
- X/*
- X * look at the first characters in each of the words to find one which
- X * one matches the amount of stuff typed so far
- X */
- Xstruct s_word *searchstr(key, str, len)
- Xchar *str;
- Xint len, key;
- X{
- X struct s_word *wordp, *best;
- X
- X for(best = NULL, prev_word = NULL, wordp = words;
- X wordp != NULL;
- X prev_word = wordp, wordp = wordp->nextword) {
- X if(wordp->length > len
- X && strncmp(wordp->word, str, len) == 0
- X && wordp->word[len] == key
- X && (!best || best->posy < wordp->posy))
- X best = wordp;
- X }
- X
- X return best;
- X}
- X
- X
- X/*
- X * look at the first character in each of the words to see if any match the
- X * one that was typed.
- X */
- Xstruct s_word *searchchar(key)
- Xchar key;
- X{
- X struct s_word *wordp, *best;
- X
- X for(best = NULL, prev_word = NULL, wordp = words; wordp != NULL;
- X prev_word = wordp, wordp = wordp->nextword) {
- X if(wordp->word[0] == key
- X && (!best || best->posy < wordp->posy))
- X best = wordp;
- X }
- X
- X return best;
- X}
- X
- Xvoid kill_word(wordp)
- Xstruct s_word *wordp;
- X{
- X struct s_word *temp, *prev = NULL;
- X
- X /*
- X * check to see if the current word is the first one on our list
- X */
- X if(wordp != words)
- X for(prev = words, temp = words->nextword; temp != wordp;) {
- X prev = temp;
- X temp = temp->nextword;
- X }
- X
- X if(prev != NULL) {
- X prev->nextword = wordp->nextword;
- X } else
- X words = wordp->nextword;
- X
- X if(wordp->nextword != NULL)
- X wordp->nextword = wordp->nextword->nextword;
- X
- X if(wordp == lastword)
- X lastword = prev;
- X
- X free((char *)wordp);
- X}
- X
- X
- X/*
- X * momentarily display a banner message across the screen and eliminate any
- X * random keystrokes form the last round
- X */
- Xvoid banner(text)
- Xchar *text;
- X{
- X /*
- X * display banner message
- X */
- X clrdisp();
- X gotoxy((SCREENWIDTH - strlen(text))/2, 10);
- X sleep(3);
- X puts(text);
- X gotoxy(SCREENWIDTH,SCREENLENGTH);
- X fflush(stdout);
- X sleep(2);
- X clrdisp();
- X
- X /*
- X * flush keyboard
- X */
- X while(key_pressed() != -1);
- X}
- END_OF_FILE
- if test 12891 -ne `wc -c <'letters.c'`; then
- echo shar: \"'letters.c'\" unpacked with wrong size!
- fi
- # end of 'letters.c'
- fi
- if test -f 'term.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'term.c'\"
- else
- echo shar: Extracting \"'term.c'\" \(3649 characters\)
- sed "s/^X//" >'term.c' <<'END_OF_FILE'
- X/*
- X * this program will attempt to draw random stuff on the screen by using the
- X * termcap library. Much of this code was evolved from term.c from the nn
- X * sources.
- X *
- X * Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X * Kim Storm deserves a fair amount of credit for this. It may not look
- X * too much like his code, but his code was at least more understandable
- X * than the documentation I was trying to work from and I'd like to give
- X * credit for making it easier for me to write.
- X *
- X * I wrote a fair amount of this based on man pages, then used Kim's code as
- X * a reference to make things work. Some of this actually ended up looking
- X * more like his code than I planned on. I hope I haven't gone overboard.
- X */
- X
- X#include <stdio.h>
- X#ifndef NEXT
- X# ifdef AMIGA
- X# include <stdlib.h>
- X# include "amitermcap.h"
- X# else
- X# include <termio.h>
- X# endif
- X#endif
- X#include <string.h>
- X#include "term.h"
- X
- Xchar *tgoto();
- Xchar PC, *BC, *UP;
- X
- Xchar *term_name;
- Xchar XBC[64], XUP[64];
- Xchar bell_str[256] = "\007";
- Xchar cursor_home[64];
- Xchar clear_screen[64];
- Xchar cursor_address[128];
- Xchar enter_standout_mode[64], exit_standout_mode[64];
- Xchar enter_underline_mode[64], exit_underline_mode[64];
- X
- Xoutc(c)
- X{
- X putchar(c);
- X}
- X
- Xbell() {
- X putp(bell_str);
- X}
- X
- Xquiet() {
- X}
- X
- Xint Lines, Columns; /* screen size */
- Xint garbage_size; /* number of garbage chars left from so */
- Xint double_garbage; /* space needed to enter&exit standout mode */
- Xint STANDOUT; /* terminal got standout mode */
- Xint TWRAP; /* terminal got automatic margins */
- X
- X/*
- X * used to get the actual terminal control string.
- X */
- Xopt_cap(cap, buf)
- Xchar *cap, *buf;
- X{
- X char *tgetstr();
- X
- X *buf = '\0';
- X return tgetstr(cap, &buf) != NULL;
- X}
- X
- X/*
- X * call opt_cap to get control string. report if the terminal lacks that
- X * capability.
- X */
- Xget_cap(cap, buf)
- Xchar *cap, *buf;
- X{
- X if (!opt_cap(cap, buf))
- X fprintf(stderr, "TERMCAP entry for %s has no '%s' capability\n",
- X term_name, cap);
- X}
- X
- X/*
- X * set everythign up. find the necessary strings to control the terminal.
- X */
- Xinit_term()
- X{
- X char tbuf[1024];
- X
- X#ifndef AMIGA
- X /*
- X * get terminal type from the environment or have the user enter it
- X */
- X if ((term_name = (char *)getenv("TERM")) == NULL) {
- X fprintf(stderr, "No TERM variable in environment\n");
- X fprintf(stderr, "Enter terminal type to use: ");
- X scanf("%s", term_name = (char *)malloc(30 * sizeof(char)));
- X }
- X#endif
- X
- X /*
- X * get the termcap entry for the terminal above
- X */
- X if (tgetent(tbuf, term_name) <= 0) {
- X fprintf(stderr, "Unknown terminal type: %s\n", term_name);
- X exit(1);
- X }
- X
- X /*
- X * get the padding character for the terminal
- X */
- X opt_cap("pc", cursor_address); /* temp. usage */
- X PC = cursor_address[0];
- X
- X get_cap("cm", cursor_address);
- X if (!opt_cap("ho", cursor_home))
- X strcpy(cursor_home, tgoto(cursor_address, 0, 0));
- X
- X get_cap("cl", clear_screen);
- X
- X Lines = tgetnum("li");
- X Columns = tgetnum("co");
- X
- X opt_cap("so", enter_standout_mode);
- X opt_cap("se", exit_standout_mode);
- X
- X opt_cap("us", enter_underline_mode);
- X opt_cap("ue", exit_underline_mode);
- X
- X garbage_size = tgetnum("sg");
- X
- X TWRAP = tgetflag("am");
- X
- X STANDOUT = HAS_CAP(enter_standout_mode);
- X if (STANDOUT) {
- X if (garbage_size < 0)
- X garbage_size = 0;
- X double_garbage = 2 * garbage_size;
- X } else
- X garbage_size = double_garbage = 0;
- X}
- X
- Xunderline(on)
- X{
- X if (garbage_size)
- X return 0;
- X if (!HAS_CAP(enter_underline_mode))
- X return 0;
- X putp(on ? enter_underline_mode : exit_underline_mode);
- X return 1;
- X}
- X
- Xhighlight(on)
- X{
- X if (garbage_size)
- X return 0;
- X if (!HAS_CAP(enter_standout_mode))
- X return 0;
- X putp(on ? enter_standout_mode : exit_standout_mode);
- X return 1;
- X}
- END_OF_FILE
- if test 3649 -ne `wc -c <'term.c'`; then
- echo shar: \"'term.c'\" unpacked with wrong size!
- fi
- # end of 'term.c'
- fi
- if test -f 'term.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'term.h'\"
- else
- echo shar: Extracting \"'term.h'\" \(397 characters\)
- sed "s/^X//" >'term.h' <<'END_OF_FILE'
- X/*
- X * header file to be used with term.c. defines some macros to place the
- X * cursor in various places on the screen.
- X *
- X * Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X */
- X
- X#define putp(str) tputs(str, 0, outc)
- X#define HAS_CAP(str) (*str)
- X#define clrdisp() tputs(clear_screen, Lines, outc)
- X#define home() putp(cursor_home)
- X#define gotoxy(c, l) putp(tgoto(cursor_address, c, l))
- X
- X#define SP ' '
- END_OF_FILE
- if test 397 -ne `wc -c <'term.h'`; then
- echo shar: \"'term.h'\" unpacked with wrong size!
- fi
- # end of 'term.h'
- fi
- if test -f 'terms.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'terms.h'\"
- else
- echo shar: Extracting \"'terms.h'\" \(723 characters\)
- sed "s/^X//" >'terms.h' <<'END_OF_FILE'
- X/*
- X * header file for term.c
- X */
- X
- Xextern char *tgoto();
- Xextern char PC, *BC, *UP;
- X
- Xextern char *term_name;
- Xextern char XBC[], XUP[];
- Xextern char bell_str[];
- Xextern char *cursor_home;
- Xextern char clear_screen[];
- Xextern char cursor_address[];
- Xextern char enter_standout_mode[], exit_standout_mode[];
- Xextern char enter_underline_mode[], exit_underline_mode[];
- X
- Xextern outc();
- Xextern bell();
- Xextern quiet();
- X
- Xextern int Lines, Columns; /* screen size */
- Xextern int garbage_size; /* number of garbage chars left from so */
- Xextern int double_garbage; /* space needed to enter&exit standout mode */
- Xextern int STANDOUT; /* terminal got standout mode */
- Xextern int TWRAP; /* terminal got automatic margins */
- END_OF_FILE
- if test 723 -ne `wc -c <'terms.h'`; then
- echo shar: \"'terms.h'\" unpacked with wrong size!
- fi
- # end of 'terms.h'
- fi
- if test -f 'usleep.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'usleep.c'\"
- else
- echo shar: Extracting \"'usleep.c'\" \(615 characters\)
- sed "s/^X//" >'usleep.c' <<'END_OF_FILE'
- X/*
- X * I grabbed this from the FAQ liston comp.unix.questions
- X */
- X/*
- X * usleep -- support routine for 4.2BSD system call emulations
- X *
- X * last edit: 29-Oct-1984 D A Gwyn
- X */
- X
- Xextern int select();
- X
- X
- Xint usleep(usec) /* returns 0 if ok, else -1 */
- Xlong usec; /* delay in microseconds */
- X{
- X static struct { /* `timeval' */
- X long tv_sec; /* seconds */
- X long tv_usec; /* microsecs */
- X } delay; /* _select() timeout */
- X
- X delay.tv_sec = usec / 1000000L;
- X delay.tv_usec = usec % 1000000L;
- X
- X return select(0, (long *) 0, (long *) 0, (long *) 0, &delay);
- X}
- END_OF_FILE
- if test 615 -ne `wc -c <'usleep.c'`; then
- echo shar: \"'usleep.c'\" unpacked with wrong size!
- fi
- # end of 'usleep.c'
- fi
- if test -f 'usleep5.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'usleep5.c'\"
- else
- echo shar: Extracting \"'usleep5.c'\" \(1575 characters\)
- sed "s/^X//" >'usleep5.c' <<'END_OF_FILE'
- X /*
- X * subseconds sleeps for System V - or anything that has poll() Don
- X * Libes, 4/1/1991
- X *
- X * The BSD analog to this function is defined in terms of microseconds
- X * while poll() is defined in terms of milliseconds. For
- X * compatibility, this function provides accuracy "over the long run"
- X * by truncating actual requests to milliseconds and accumulating
- X * microseconds across calls with the idea that you are probably
- X * calling it in a tight loop, and that over the long run, the error
- X * will even out.
- X *
- X * If you aren't calling it in a tight loop, then you almost certainly
- X * aren't making microsecond-resolution requests anyway, in which
- X * case you don't care about microseconds. And if you did, you
- X * wouldn't be using UNIX anyway because random system indigestion
- X * (i.e., scheduling) can make mincemeat out of any timing code.
- X *
- X * Returns 0 if successful timeout, -1 if unsuccessful.
- X *
- X */
- X
- X#include <poll.h>
- X
- X int
- X usleep(usec)
- X unsigned int usec; /* microseconds */
- X {
- X static subtotal = 0; /* microseconds */
- X int msec; /* milliseconds */
- X
- X /*
- X * 'foo' is only here because some versions of 5.3 have a bug
- X * where the first argument to poll() is checked for a valid
- X * memory address even if the second argument is 0.
- X */
- X struct pollfd foo;
- X
- X subtotal += usec;
- X /* if less then 1 msec request, do nothing but remember it */
- X if (subtotal < 1000)
- X return (0);
- X msec = subtotal / 1000;
- X subtotal = subtotal % 1000;
- X return poll(&foo, (unsigned long) 0, msec);
- X }
- END_OF_FILE
- if test 1575 -ne `wc -c <'usleep5.c'`; then
- echo shar: \"'usleep5.c'\" unpacked with wrong size!
- fi
- # end of 'usleep5.c'
- fi
- if test -f 'word.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'word.c'\"
- else
- echo shar: Extracting \"'word.c'\" \(1479 characters\)
- sed "s/^X//" >'word.c' <<'END_OF_FILE'
- X/*
- X * find a random word in a dictionary file as part of letters.
- X *
- X * copyright 1991 Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "config.h"
- X#include "kinput.h"
- X
- X#ifdef SYSV
- X# define random lrand48
- X#endif
- X
- Xchar *getword()
- X{
- X static char buf[512];
- X static FILE *fp = NULL;
- X static struct stat s_buf;
- X
- X /*
- X * This is stuff that only needs to get done once.
- X */
- X if(fp == NULL) {
- X char *dictionary = DICTIONARY;
- X
- X /*
- X * open the dictionary file
- X */
- X if((fp = fopen(dictionary, "r")) == NULL) {
- X fprintf(stderr, "can't open file: %s.\n", dictionary);
- X setterm(ORIG);
- X exit(1);
- X }
- X
- X /*
- X * Get length of dictionary in bytes so we can pick a
- X * random entry in it.
- X */
- X if(stat(dictionary, &s_buf) == -1) {
- X perror("stat");
- X setterm(ORIG);
- X exit(1);
- X }
- X }
- X
- X /*
- X * pick a random place in the dictionary
- X */
- X fseek(fp, random() % s_buf.st_size, 0);
- X
- X /*
- X * read until the end of a line, then read the next word.
- X */
- X fscanf(fp, "%*s%s", buf);
- X
- X /*
- X * Since we're reading two words at a time it's possible to go past
- X * the end of the file. If that happens, use the first word in the
- X * dictionary.
- X */
- X if(buf == NULL) {
- X fseek(fp, 0L, 0);
- X fscanf(fp, "%s", buf);
- X }
- X
- X return buf;
- X}
- X
- X
- Xchar *bonusword()
- X{
- X static char buf[BONUSLENGTH + 1];
- X int i;
- X
- X for(i = 0; i < BONUSLENGTH; i++)
- X buf[i] = (char)(random() % 94) + 33;
- X
- X buf[BONUSLENGTH] = 0;
- X
- X return buf;
- X}
- END_OF_FILE
- if test 1479 -ne `wc -c <'word.c'`; then
- echo shar: \"'word.c'\" unpacked with wrong size!
- fi
- # end of 'word.c'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(2243 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- X# Makefile for letters, a game to help improve typing skills
- X#
- X# copyright 1991 by Larry Moss (lm03_cif@uhura.cc.rochester.edu)
- X#
- X
- XCC = cc
- X#CC = gcc
- X#SYSTYPE = SYSV
- X#SYSTYPE = NEXT
- XSYSTYPE = BSD
- X# if you don't have job control add -DNOJOB to CFLAGS
- XCFLAGS = -O -D$(SYSTYPE) -DHIGHSCORES=\"$(LIBDIR)/letters.high\" \
- X -DDICTIONARY=\"$(DICTIONARY)\"
- XLDFLAGS = -ltermcap
- XBINDIR = $(HOME)/bin-sun4
- XMANDIR = $(HOME)/man/man$(MANEXT)
- XMANEXT = 6
- XLIBDIR = $(HOME)/lib
- XDICTIONARY = /usr/dict/words
- X#DICTIONARY = dictfile
- X
- X# next line only needed if you need to create a dictionary file. The files
- X# in this directory will be used to make a wordlist.
- XDOCDIR = $(HOME)/man
- X
- X# If your machine doesn't have usleep uncomment it in the following line.
- X# I know this includes ultrix 4.2 and hp-ux 7.? and many sys V based machines.
- X# Don't know about others. if you need usleep and your machine does not have
- X# select, change usleep.o to usleep5.o (mostly sysV machines).
- XOBJS = letters.o kinput.o term.o word.o highscore.o # usleep.o
- X
- X# The following line will stop gcc from complaining about the arguments
- X# sun's make uses. It shouldn't bother anyone else.
- X.c.o:
- X $(CC) $(CFLAGS) -c $<
- X
- Xletters: $(OBJS)
- X $(CC) $(CFLAGS) $(OBJS) -o letters $(LDFLAGS)
- X
- Xletters.o word.o kinput.o: \
- X kinput.h
- Xletters.o term.o highscore.o kinput.o: \
- X term.h
- Xletters.o highscore.o kinput.o: \
- X terms.h
- Xword.o highscore.o letters.o: \
- X config.h
- X
- Xinstall: letters
- X install -s -m 2755 letters $(BINDIR)
- X sed -e 's;LIBDIR;$(LIBDIR);' -e 's;DICTIONARY;$(DICTIONARY);'\
- X letters.man > letters.$(MANEXT)
- X install -c -m 0644 letters.$(MANEXT) $(MANDIR)/letters.$(MANEXT)
- X if [ ! -f $(LIBDIR)/letters.high ] ;then \
- X install -c -m 0664 letters.high $(LIBDIR) ;fi
- X
- Xinstall_hpux: letters
- X install -c $(BINDIR) letters
- X install -c $(MANDIR) letters.man
- X install -c $(LIBDIR) letters.high
- X chmod 0666 $(LIBDIR)/letters.high
- X
- Xclean:
- X rm -f rm *.o letters letters.$(MANEXT)
- X
- Xshar:
- X shar -o letters.shar *.[ch] Makefile letters.man letters.high README
- X
- Xtar:
- X tar cf letters.tar *.[ch] Makefile letters.man letters.high README
- X
- Xdict:
- X awk '{ for (i = 0; i <= NF; ++i)\
- X if($$i ~ /^[a-zA-Z][a-z]*$$/) { print $$i } }'\
- X `find $(DOCDIR) -type f -print` |\
- X sort -u > $(DICTIONARY)
- END_OF_FILE
- if test 2243 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'letters.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'letters.man'\"
- else
- echo shar: Extracting \"'letters.man'\" \(4572 characters\)
- sed "s/^X//" >'letters.man' <<'END_OF_FILE'
- X.TH LETTERS 6 "23 SEPT 1991"
- X.SH NAME
- Xletters \- a game to improve typing skills
- X.SH SYNOPSIS
- X\fBletters\fP [-q | -b] [-l#]
- X.br
- X\fBletters\fP [-h]
- X.SH DESCRIPTION
- X\fBLetters\fP is based on \fBLetter Invaders\fP which was around in the PC
- Xenvironment several years ago. It in turn was based on the popular
- Xarcade style game, \fBSpace Invaders\fP. For those not familiar with
- X\fBSpace Invaders\fP \ (please let me know if you're one of these people
- Xand let me know what planet you've been living on :-) the idea is to blast
- Xaliens out of the sky as they attempt to land on and "kill" you. Since
- Xthis is a game to improve typing skills, the aliens are words selected
- Xrandomly from the dictionary. You blast the aliens out of the sky by
- Xtyping them correctly.
- X.PP
- XPlaying the game is very straight forward. Type words as they appear on
- Xthe screen. They will slowly drop until you have either typed them
- Xcorrectly or they reach the status line on the bottom of the screen. If
- Xa word makes it to the bottom of the screen you lose one "life". This is
- Xactually a non-violent game. The words "kill" and "life" are only used
- Xin this context for historical reasons.
- X.PP
- XIf at any point you type a letter incorrectly the entire word is reset.
- XThe backspace key will not save you if you're a sloppy typist.
- XIt is not necessary to type words in the order they appear on the
- Xscreen. In fact, that is often not the
- Xbest action to take. Very short words fall faster than longer ones.
- XThe program will attempt to determine the word you are
- Xtrying to type by matching what you've typed with the first letter(s) of
- Xall other words on the screen. Unlike in previous versions the program
- Xtries to determine what word you are typing by more than the first
- Xletter. The highlight bar doesn't move to a new word until it is clear
- Xwhich word is being typed.
- X.PP
- XIf you successfully complete 3 rounds of play you get a bonus life and
- Xyou get the opportunity to play a bonus round. The bonus round is played
- Xthe same as all other rounds but the words are strings of random
- Xprintable characters. The round is played at the same speed as whatever
- Xlevel you were on and likewise points are computed the same as in that
- Xround. since this is just a bonus round, you can only gain points. You
- Xcannot die. The round lasts as long as all other rounds (15 words)
- Xunless a word reaches the bottom of the screen.
- X.SH "Special Keys"
- X.IP
- Xctrl-L Redraw screen.
- X.IP
- Xctrl-C Exit from the game. You will be prompted before exiting to make
- Xsure that's really what you wanted to do. Since it prompts you this can
- Xalso be used as a method of pausing the game. This is actually whatever
- Xyour interrupt character is. Ctrl-C is just most common.
- X.IP
- Xctrl-N Skip to next level. The game does correctly keep track of how
- Xmany levels you have completed. (See '-l' under \fBOPTIONS\fP)
- X.IP
- Xctrl-Z Works as it should. If your system has job control it will stop
- Xthe process.
- X.SH OPTIONS
- X.IP
- X-q quiet mode (default) - turn off the obnoxious beep
- X.IP
- X-h Show high scores.
- X.IP
- X-b Beep when words are completed or mistyped.
- X.IP
- X-l# # is the level number that you want to start at. The level will
- Xnot increase until you have completed the number of rounds equal to your
- Xstarting level. In other words, if you start on level 5, you need to
- Xplay through 5 rounds before the level increases to 6 (and the speed
- Xincreases and scoring changes).
- X.SH SCORING
- XA word's point value = (# of letters) + 2 * (current level). No points
- Xare added for partially typed words.
- X.SH "STATUS LINE"
- XIt's fairly obvious what most of the things on the status line are. The
- Xlast thing on the line however is words per minute. This is computed at
- Xthe end of each round based on 5 letter words. It's not a particularly
- Xaccurate measure of your typing speed, but I think it's an interesting
- Xenough statistic to justify filling up the empty space on the status line.
- X.SH FILES
- XDICTIONARY
- X.br
- XLIBDIR/letters.high
- X.SH BUGS
- X"Transmogrifier" doesn't appear frequently.
- X.SH AUTHORS
- XLarry Moss (lm03_cif@uhura.cc.rochester.edu) - original game, UNIX version
- X.br
- XBrent Nordquist (brent@limabean.veggard.mn.org) - amiga version, also
- Xfixed some of bugs.
- X.SH THANKS
- XChris Uppal (chrisu@sco.com) for contributing enormously to the
- Xprogram with a couple of bug fixes, variable speed words, some
- Xperformance improvements, SYSV compatibility, and many suggestions.
- X.sp
- XMark Levinson (mrle_cif@uhura.cc.rochester.edu) for pointing out the bug
- Xlisted above.
- X.sp
- XThanks also to everyone else that's sent me mail with comments and/or
- Xsuggestions.
- END_OF_FILE
- if test 4572 -ne `wc -c <'letters.man'`; then
- echo shar: \"'letters.man'\" unpacked with wrong size!
- fi
- # end of 'letters.man'
- fi
- if test -f 'letters.high' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'letters.high'\"
- else
- echo shar: Extracting \"'letters.high'\" \(175 characters\)
- sed "s/^X//" >'letters.high' <<'END_OF_FILE'
- Xhfir_cif 9 121 871hfir_cif 8 115 850hfir_cif 8 106 818hfir_cif 8 113 803lm03_cif 6 82 633lm03_cif 6 85 611jcm8_cif 6 78 557jcm8_cif 5 74 522jcm8_cif 4 47 366jcm8_cif 4 47 352
- END_OF_FILE
- if test 175 -ne `wc -c <'letters.high'`; then
- echo shar: \"'letters.high'\" unpacked with wrong size!
- fi
- # end of 'letters.high'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3963 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XLetter Invaders v2.1
- XA game to help improve typing skills.
- X=====================================
- X
- XCopying:
- X
- XPlease put this on as many different machines as you like. If you make
- Xchanges or bug fixes, please mail them to me so they can be incorporated
- Xinto later versions. Feel free to use the entire program or portions of
- Xit in any way you like as long as I get credit for what I've done.
- X
- X
- XInstallation:
- X
- XInstallation of letters should be fairly simple. A few lines in the
- XMakefile should be changed to reflect the directories where the files
- Xshould be installed. Config.h may (but shouldn't) require a couple of
- Xchanges. After making the minor changes, "make install" or "make
- Xinstall_hpux" should do all the work. The hpux installation could be
- Ximproved, but it is enough to get it up and running. If your system does
- Xnot have /usr/dict/words or any other large collection of words you can
- Xuse "make dict" to create a wordlist. Well, it works for me, but I use
- Xawk to do it so I know someone is bound to have a problem.
- X
- XSo far it has been compiled and run under SunOS 4.0 and 4.1.1, SCO Xenix,
- XULTRIX 4.2, hpux 7.05, and NeXT (mach, I guess) and a large number of
- Xothers. When compiling it on the NeXT it produces a number of warnings
- Xbut there are no serious problems (I'd fix it, but my access to a NeXT is
- Xfairly limited so I just made sure it compiles). Please let me know
- Xabout any other platforms that it gets compiled on or fails to get
- Xcompiled on.
- X
- XThe game has been ported to the amiga. A large portion of the code
- Xnecessary to make it compile on the amiga is not included with the UNIX
- Xdistribution. All UNIX specific and Amiga specific stuff has been kept
- Xseparate so that it will be easy to keep versions the same if/when the
- Xgame is improved.
- X
- XI'd like to mention that there is a minix version of the game available.
- XThe changes to make it compile under minix are not included in this
- Xpackage (although there have been enough changes to accomodate other
- Xsystems that it might not be too much work any more to get it to compile
- Xon minix). Credit for the minix version (and comments and questions) to
- XWim van Dorst (baron@wiesje.hobby.nl). I've been told the minix version
- Xcan be foundon your favorite minix archive site.
- X
- Xauthors
- X-------
- XLarry Moss (lm03_cif@uhura.cc.rochester.edu) - original game, UNIX version
- XBrent J. Nordquist (brent@limabean.veggard.mn.org) - amiga version
- X
- X
- XThanks to:
- X----------
- X
- XD. A. Gwyn. I have used his code for usleep() to get it to compile on
- Xmachines that don't have it. Since the code is included in the FAQ
- Xposted to comp.unix.questions I assume this is ok. If someone knows
- Xotherwise please let me know.
- X
- XKim Storm. I used his nn code as a reference when trying to figure out
- Xhow to use the termcap library.
- X
- XChris Uppal (chrisu@sco.com). He has contributed enormously to the
- Xprogram with a couple of bug fixes, variable speed words, some
- Xperformance improvements, SYSV compatibility, and many suggestions.
- X
- XWim van Dorst (baron@wiesje.hobby.nl). Creator of the minix version of
- Xthe game.
- X
- X
- X
- XFuture plans:
- X
- XI had at one time planned to have bonus words fly horizontally across
- Xscreen, but I never bothered with implementing it. Instead, I just got a
- Xsuggestion to have the bonus words come down like the others, but
- Xunderlined. When a bonus word is typed correctly it will take out the
- Xwhole screen with it. This could add a bit of strategy to the game.
- X
- Xinteresting things should happen at higher levels. Now it just keeps
- Xgetting faster. I've gotten the suggestion of possibly having some words
- Xon the screen change randomly to force you to watch the screen more
- Xcarefully.
- X
- XI've considered using this as an excuse to learn X programming. I figure
- Xthat way words can really explode. This will only happen if I find
- Xmyself with a lot of free time.
- X
- XFrequently mistyped words should come back later in the game. This would
- Xcertainly make the game more useful as a typing tutor.
- END_OF_FILE
- if test 3963 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- echo shar: End of shell archive.
- exit 0
-